package com.czg.jsonschema2lombokpojo.annotator;

import com.czg.jsonschema2lombokpojo.config.GenerationConfig;
import com.fasterxml.jackson.databind.JsonNode;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JEnumConstant;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;

/**
 * 为生成的类型添加注解，以兼容JSON序列化库。
 * <p>
 * 需要生成配置的注解器应该添加一个带有{@link GenerationConfig}参数的构造器。不需要配置的注解器只需要添加一个默认构造函数。
 */
public interface Annotator {

    /**
     * 添加必要的注解，以在序列化和反序列化期间口述正确的类型信息；通常需要多态类型。
     *
     * @see <a
      *      href="https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization">杰克逊文档-多态类型处</a>
     *
     * @param clazz
     *            生成pojo类，需要序列化注解
     * @param schema
     *            与此相关的对象schema
     */
    void typeInfo(JDefinedClass clazz, JsonNode schema, boolean isEnum);


    /**
     * 添加必要的注解，使序列化过程中只包含非空值。
     *
     * @param clazz
     *            生成pojo类，需要序列化注解
     * @param schema
     *            与此相关的对象schema
     */
    void propertyInclusion(JDefinedClass clazz, JsonNode schema);

    /**
     * 添加必要的注解来将Java字段标记为JSON属性
     *
     * @param field
     *            包含将被序列化的数据的字段
     * @param clazz
     *            生成pojo类，需要序列化注解
     * @param propertyName
     *            该字段所代表的JSON属性的名称
     * @param propertyNode
     *            定义此属性的schema节点
     */
    void propertyField(JFieldVar field, JDefinedClass clazz, String propertyName, JsonNode propertyNode);


    /**
     * 添加必要的注解，将Java方法标记为与bean中发现的任何其他属性名不匹配的附加JSON属性值的getter。
     *
     * @param getter
     *            用于获取附加属性值的方法
     * @param clazz
     *            生成pojo类，需要序列化注解
     */
    void anyGetter(JMethod getter, JDefinedClass clazz);

    /**
     * 添加必要的注解，将Java方法标记为与bean中发现的任何其他属性名不匹配的附加JSON属性值的设置器。
     *
     * @param setter
     *            用于设置附加属性值的方法
     * @param clazz
     *            生成pojo类，需要序列化注解
     */
    void anySetter(JMethod setter, JDefinedClass clazz);

    /**
     * 添加必要的注解，将静态Java方法标记为创建者/工厂方法，可以在反序列化期间为给定的JSON值选择正确的Java enum值。
     *
     * @param _enum
     *           生成的枚举类，需要序列化注解
     * @param creatorMethod
     *            可以从JSON值创建Java枚举值的方法
     */
    void enumCreatorMethod(JDefinedClass _enum, JMethod creatorMethod);

    /**
     * 添加必要的注解，将Java方法标记为用于在序列化期间将Java枚举值转换为JSON值的值方法。
     *
     * @param _enum
     *            生成的枚举类，需要序列化注解
     * @param valueMethod
     *            枚举实例方法，可以在序列化期间创建JSON值
     */
    void enumValueMethod(JDefinedClass _enum, JMethod valueMethod);

    /**
     * 在枚举常量中添加必要的注解。例如，在序列化时强制使用给定的值。
     *
     * @param _enum
     *            生成的枚举类，需要序列化注解
     * @param constant
     *            _enum中的常量之一
     * @param value
     *            序列化该常量时使用的值
     */
    void enumConstant(JDefinedClass _enum, JEnumConstant constant, String value);

    /**
     * 指示该注解器使用的注解样式是否支持JSONschema的“additionalProperties”特性。换句话说，与此注解样式相关联的反序列化器能否收集意外的、额外的json属性，以及它是否希望将它们包含在目标Java实例中的某个地方。
     * <p>
     * 杰克逊能够使用它的<code>JsonAnyGetter</code>和<code>JsonAnySetter</code>功能为此目的，
     * 因此，对于Jackson注解器，此方法将返回<code>true</code>。Gson不支持“附加”属性值（它们在反序列化时被静默丢弃），
     * 因此对于Gson注解器，此方法将返回<code>false</code>。
     * Moshi 1；x的行为类似于Gson，因此返回<code>false</code>。
     *
     * @return 这个注解器是否有任何方式支持“附加属性”。
     */
    boolean isAdditionalPropertiesSupported();

    /**
     * 在日期-时间字段中添加必要的注解。例如，以期望的样式格式化日期时间。
     *
     * @param field
     *            包含将被序列化的数据的字段
     * @param clazz
     *            生成pojo类，需要序列化注解
     * @param propertyNode
     *            定义此属性的schema节点
     */
    void dateTimeField(JFieldVar field, JDefinedClass clazz, JsonNode propertyNode);

    /**
     * 为日期字段添加必要的注解。例如，以期望的样式格式化日期。
     *
     * @param field
     *            包含将被序列化的数据的字段
     * @param clazz
     *            生成pojo类，需要序列化注解
     * @param propertyNode
     *            定义此属性的schema节点
     */
    void dateField(JFieldVar field, JDefinedClass clazz, JsonNode propertyNode);

    /**
     * 在时间字段中添加必要的注释。例如，以期望的样式格式化时间。
     *
     * @param field
     *            包含将被序列化的数据的字段
     * @param clazz
     *            生成pojo类，需要序列化注解
     * @param propertyNode
     *            定义此属性的schema节点
     */
    void timeField(JFieldVar field, JDefinedClass clazz, JsonNode propertyNode);


    /**
     * 是否应该添加类型提示注释来支持多态反序列化。
     *
     * @param node
     *            相关的schema节点
     *
     * @return <code>true</code> 如果JSON库支持多态反序列化并且该schema中存在deserializationClassProperty
     */
    boolean isPolymorphicDeserializationSupported(JsonNode node);
}
